package com.harzone.commons.search.statement;

import java.io.Closeable;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.harzone.commons.search.domain.AFunctions;
import com.harzone.commons.search.domain.Field;
import com.harzone.commons.search.domain.From;
import com.harzone.commons.search.domain.Group;
import com.harzone.commons.search.domain.MethodField;
import com.harzone.commons.search.domain.MethodOrder;
import com.harzone.commons.search.domain.Order;
import com.harzone.commons.search.domain.Order.OrderType;
import com.harzone.commons.search.domain.SortFunctions;
import com.harzone.commons.search.visitor.StatementVisitor;

/**
 * 搜索信息实体
 * @author ls
 * 2014年11月21日下午2:34:54
 */
public class Select extends BaseWhere implements Serializable,Closeable,Statement{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private List<Field> fields = new ArrayList<Field>();
	private List<From> froms = new ArrayList<From>();
	private List<Group> groupBys = new ArrayList<Group>();
	private List<Order> orderBys = new ArrayList<Order>();
	private int offset = 0;
	private int rowCount = 10;

	public boolean isQuery = false;

	/**
	 * 是否存在聚合函数
	 */
	public boolean isAgg = false;
	
	/**
	 * 是否分组
	 */
	public boolean isGroup = false;
	
	
	public Select() {
	}

	
	public void addGroupBy(String name) {
		this.addGroupBy(new Group(name));
	}

	public void addGroupBy(Group field) {
		isGroup = true;
		this.groupBys.add(field);
	}
	
	public void addOrderBy(String name, String type) {
		this.addOrderBy(name, OrderType.get(type));
	}


	/**
	 * 添加一个降序排序条件
	 * @author ls
	 * 2014年11月22日下午4:31:21 
	 * @param name
	 */
	public void addOrderBy(String name) {
		this.addOrderBy(name, OrderType.DESC);
	}
	
	
	public void addOrderBy(String name, OrderType type) {
		if ("_score".equals(name)) {
			isQuery = true;
		}
		this.orderBys.add(new Order(name, type));
	}

	
	/**
	 * 排序方法
	 * @author ls
	 * 2014年11月26日下午12:30:21 
	 * @param name
	 * @param type
	 * @return
	 */
	public MethodOrder addMethodOrderBy(String name, OrderType type) {
		MethodOrder m = new MethodOrder(name, type);
		this.orderBys.add(m);
		return m;
	}
	
	public MethodOrder addMethodOrderBy(SortFunctions sf, OrderType type) {
		MethodOrder m = new MethodOrder(sf, type);
		this.orderBys.add(m);
		return m;
	}
	
	
	/**
	 * 排序方法
	 * @author ls
	 * 2014年11月26日下午12:31:30 
	 * @param name
	 * @param type
	 * @return
	 */
	public MethodOrder addMethodOrderBy(String name, String type) {
		MethodOrder m = new MethodOrder(name, OrderType.get(type));
		this.orderBys.add(m);
		return m;
	}
	
	public MethodOrder addMethodOrderBy(SortFunctions sf, String type) {
		MethodOrder m = new MethodOrder(sf, OrderType.get(type));
		this.orderBys.add(m);
		return m;
	}
	
	public MethodField addMethodField(AFunctions af) {
		MethodField m = new MethodField(af);
		fields.add(m);
		return m;
	}
	
	public void addField(String name) {
		fields.add(new Field(name));
	}
	
	public void addField(Field field) {
		if (field == null) {
			return;
		}
		if (field instanceof MethodField) {
			switch (field.getName()) {
			case "SUM":
			case "MAX":
			case "MIN":
			case "AVG":
			case "TOPHITS":
			case "COUNT":
//				if (!"*".equals(((MethodField) field).getParams().get(0).toString())) {
//					isAgg = true;
//				}
				isAgg = true;
			default :
				return ;
			}
		}
		fields.add(field);
	}

	
	public void addForm(String name){
		this.froms.add(new From(name));
	}
	
	
	public List<Field> getFields() {
		return fields;
	}

	public void setOffset(int offset) {
		this.offset = offset;
	}

	public void setRowCount(int rowCount) {
		this.rowCount = rowCount;
	}

	public List<Group> getGroupBys() {
		return groupBys;
	}

	public List<Order> getOrderBys() {
		return orderBys;
	}

	public int getOffset() {
		return offset;
	}

	public int getRowCount() {
		return rowCount;
	}


	@Override
	public String toString() {
		return "Select [fields=" + fields + ", froms=" + froms + ", groupBys="
				+ groupBys + ", orderBys=" + orderBys + ", offset=" + offset
				+ ", rowCount=" + rowCount + ", isQuery=" + isQuery
				+ ", isAgg=" + isAgg + "]"+super.toString();
	}


	@Override
	public void close() throws IOException {
		this.fields.clear();
		this.froms.clear();
		this.groupBys.clear();
		this.orderBys.clear();
	}
	
	@Override
	public void accept(StatementVisitor statementVisitor) {
		statementVisitor.visit(this);
	}
}
